////////////////////////////////////////////////////////////////////////////
//
//  CryEngine Source File.
//  Copyright (C), Crytek.
// -------------------------------------------------------------------------
//  File name:   StreamReadStream.h
//  Created:     27/07/2010 by Timur.
//  Description: Streaming Engine
// -------------------------------------------------------------------------
//  History:
//
////////////////////////////////////////////////////////////////////////////

#ifndef _CRY_SYSTEM_READ_STREAM_PROXY_HDR_
#define _CRY_SYSTEM_READ_STREAM_PROXY_HDR_

#include "IStreamEngine.h"
#include "StreamAsyncFileRequest.h"

class CStreamEngine;

class CReadStream: public IReadStream
{
public:
	CReadStream ( CStreamEngine *pEngine,const EStreamTaskType tSource, const char *szFilename, IStreamCallback* pCallback, StreamReadParams* pParams);
	virtual ~CReadStream ();

	VIRTUAL DWORD_PTR GetUserData() {return m_Params.dwUserData;}

	// set user defined data into stream's params
	VIRTUAL void SetUserData(DWORD_PTR dwUserData);

	// returns true if the file read was not successful.
	VIRTUAL bool IsError() { return m_bError; };

	// returns true if the file read was completed (successfully or unsuccessfully)
	// check IsError to check if the whole requested file (piece) was read
	VIRTUAL bool IsFinished();

	// returns the number of bytes read so far (the whole buffer size if IsFinished())
	VIRTUAL unsigned int GetBytesRead (bool bWait);

	// returns the buffer into which the data has been or will be read
	// at least GetBytesRead() bytes in this buffer are guaranteed to be already read
	VIRTUAL const void* GetBuffer ();

	// tries to stop reading the stream; this is advisory and may have no effect
	// but the callback	will not be called after this. If you just destructing object,
	// dereference this object and it will automatically abort and release all associated resources.
	VIRTUAL void Abort();

	// tries to raise the priority of the read; this is advisory and may have no effect
	VIRTUAL void SetPriority (EStreamTaskPriority EPriority);

	// unconditionally waits until the callback is called
	// i.e. if the stream hasn't yet finish, it's guaranteed that the user-supplied callback
	// is called before return from this function (unless no callback was specified)
	VIRTUAL void Wait( int nMaxWaitMillis=-1 );

	VIRTUAL uint64 GetPriority()const;

	VIRTUAL const StreamReadParams& GetParams() const {return m_Params;}

  VIRTUAL const EStreamTaskType GetCallerType() const { return m_Type; }

	// return pointer to callback routine(can be NULL)
	VIRTUAL IStreamCallback* GetCallback() const;

	// return IO error #
	VIRTUAL unsigned GetError() const; 

	//	 Returns IO error name
	VIRTUAL const char* GetErrorName() const; 

	// return stream name
	VIRTUAL const char* GetName() const { return m_strFileName.c_str(); };

	// call the async callback 
	VIRTUAL void ExecuteAsyncCallback();

	// call the sync callback 
	VIRTUAL void ExecuteSyncCallback();

	VIRTUAL void FreeTemporaryMemory();

	// this gets called upon the IO has been executed to call the callbacks
	void MainThread_Finalize();

	bool IsReqReading();

	void SetRequestTime(CTimeValue& time) { m_requestTime = time; }
	const CTimeValue& GetRequestTime() { return m_requestTime; }

	// decompression of zip-compressed files with default behavior
	CAsyncIOFileRequest* CreateFileRequest();
	void OnAsyncFileRequestComplete();
	CAsyncIOFileRequest* GetFileRequest() { return m_pFileRequest; }

protected:
	friend class CStreamEngine;

	CStreamEngine* m_pEngine;
	
	// the type of the task
	const EStreamTaskType				m_Type;
	// the initial data from the user
	StreamReadParams						m_Params;
	// the callback; may be NULL
	IStreamCallback*						m_pCallback;

	// Bytes actually read from media.
	uint32 m_nBytesRead;
	// Time for actual reading
	CTimeValue m_ReadTime;

	volatile bool								m_bIsAsyncCallbackExecuted;
	volatile bool								m_bIsSyncCallbackExecuted;
	volatile bool               m_bFileRequestComplete;

	// the actual buffer to read to
	void* m_pBuffer;

	// time when request was made
	CTimeValue m_requestTime;

	volatile bool m_bError;
	volatile bool m_bFinished;
	unsigned int m_nIOError;

	CryStringLocal m_strFileName;

	CryCriticalSection m_callbackLock;

	CAsyncIOFileRequest_AutoPtr m_pFileRequest;
};

TYPEDEF_AUTOPTR(CReadStream);

#endif
